<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="test">尚硅谷IT教育</div>

    <div id="app">
      <ul>
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
      </ul>
    </div>

    <!--
1. [].slice.call(lis): 将伪数组转换为真数组
2. node.nodeType: 得到节点类型
3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
6. DocumentFragment: 文档碎片(高效批量更新多个节点)
-->

    <script type="text/javascript">
      /*
      1. [].slice.call(lis): 将伪数组转换为真数组
      2. node.nodeType: 得到节点类型
      3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
      4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
      5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
      6. DocumentFragment: 文档碎片(高效批量更新多个节点)
      */

      // 1. [].slice.call(lis): 将伪数组转换为真数组
      const lis = document.querySelectorAll("li");
      console.log(lis);
      const arr = [].slice.call(lis);
      // const arr = Array.prototype.slice.call(lis);
      console.log(arr);

      // 2. node.nodeType 节点类型、DOM元素
      // https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeType
      // 1 代表元素节点
      // 3 代表文本节点
      console.log(arr[0].nodeType);

      // 3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
      const person = {};

      Object.defineProperty(person, "name", {
        value: "jack",
        writable: true, // 是否可写
        configurable: false, // 是否可重新配置或删除（delete）
        enumerable: true, // 是否遍历 for in
      });

      // 4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
      const p = { name: "jack", age: 18 };
      console.log(Object.keys(p)); // ['name', 'age']
      console.log(Object.values(p)); // ['jack', 18]

      // 5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
      // 直接属性返回值true
      // 原型上的属性返回值false
      const p1 = { a: 1 };
      p1.__proto__.b = 2;

      for (const key in p1) {
        console.log("外", key);
        if (p1.hasOwnProperty(key)) {
          console.log("内", key);
        }
      }

      // 6. DocumentFragment: 文档碎片(高效批量更新多个节点)
      const fragment = document.createDocumentFragment();
      // console.dir(fragment);
      const app = document.getElementById("app");
      console.dir(app);

      // let fc = app.firstChild;
      // // console.log(fc);
      // while (fc) {
      //   // 当将节点添加到文档碎片中，会自动从dom树中删除
      //   fragment.appendChild(fc);
      //   fc = app.firstChild
      // }

      // 1. 将DOM元素添加到文档碎片节点中
      let child;
      while ((child = app.firstChild)) {
        fragment.appendChild(child);
      }
      console.dir(fragment);

      // 2. 通过fragment操作DOM
      [].slice.call(fragment.childNodes).forEach((node) => {
        if (node.nodeType === 1) {
          [].slice.call(node.childNodes).forEach((node) => {
            if (node.nodeType === 1) {
              node.textContent = node.textContent + "~~~~";
            }
          });
        }
      });

      // 3. 将操作好的fragment添加app中生效
      app.appendChild(fragment);
    </script>
  </body>
</html>
